﻿using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Excel = NetOffice.ExcelApi;
using Autodesk.AutoCAD.DatabaseServices;
using System.IO;
using Autodesk.AutoCAD.Geometry;
namespace _17外部文件_Excel_交互
{
    public class Class1
    {
        public struct CircleData
        {
            public double X;
            public double Y;
            public double Z;
            public double R;
        }

        [CommandMethod("ExcelDemo")]
        public void ExcelDemo()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            #region 保存图形信息到Excel文件
            //string fileName = this.OpenSaveDialog(ed, db);
            //if (fileName == "") return;
            ////获取图形信息
            //TypedValue[] values = new TypedValue[]
            //{
            //    new TypedValue((int)DxfCode.Start,"circle")
            //};
            //SelectionFilter filter = new SelectionFilter(values);
            //PromptSelectionResult res = ed.SelectAll(filter);
            //if (res.Status != PromptStatus.OK) return;

            //ObjectId[] ids = res.Value.GetObjectIds();
            //if (ids.Length == 0) return;
            //CircleData[] datas = this.GetCircelData(db, ids);
            ////保存数据到Excel文件
            //this.SaveDataToExcel(fileName, datas);
            #endregion

            #region 读取Excel文件画图
            
            string fileName = this.OpenFileDialog(ed, db);
            if (fileName == "") return;
           
            List<CircleData> datas = this.GetDataFromExcel(fileName);
            if (datas.Count == 0) return;

            this.DrawCircle(db, datas);
            #endregion
        }
        /// <summary>
        /// 将图形绘制到模型空间
        /// </summary>
        /// <param name="db"></param>
        /// <param name="datas"></param>
        private void DrawCircle(Database db, List<CircleData> datas)
        {
            using (Transaction trasns = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)trasns.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)trasns.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                for (int i = 0; i < datas.Count; i++)
                {
                    
                    Point3d center = new Point3d(datas[i].X, datas[i].Y, datas[i].Z);
                    double radius = datas[i].R;
                    Circle c = new Circle(center,Vector3d.ZAxis,radius);
                    btr.AppendEntity(c);
                    trasns.AddNewlyCreatedDBObject(c, true);
                }
                trasns.Commit();
            }
        }

        /// <summary>
        /// 读取Excel数据
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private List<CircleData> GetDataFromExcel(string fileName)
        {
            List<CircleData> datas = new List<CircleData>();
            Excel.Application excelApp = new Excel.Application(); //生命Excel程序
            Excel.Workbook book = excelApp.Workbooks.Open(fileName); //Excel工作簿
            Excel.Worksheet sheet = (Excel.Worksheet)book.Worksheets[1]; //获取第一张工作表
            int i = 2;
            while (sheet.Cells[i, 2].Value != null && sheet.Cells[i, 2].Value.ToString().Trim() != "")
            {
                CircleData data = new CircleData();
                data.R = (double)sheet.Cells[i, 2].Value;
                data.X = (double)sheet.Cells[i, 3].Value;
                data.Y = (double)sheet.Cells[i, 4].Value;
                data.Z = (double)sheet.Cells[i, 5].Value;
                datas.Add(data);
                i++;
            }
            excelApp.Quit(); //推出并销毁Excel程序
            excelApp.Dispose();
            return datas;
        }

        /// <summary>
        /// 保存数据到Excel文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="datas"></param>
        private void SaveDataToExcel(string fileName, CircleData[] datas)
        {
            Excel.Application excelApp = new Excel.Application(); //生命Excel程序
            Excel.Workbook book = excelApp.Workbooks.Add(); //Excel工作簿
            Excel.Worksheet sheet = (Excel.Worksheet)book.Worksheets[1]; //获取第一张工作表
            sheet.Cells[1, 1].Value = "序号";
            sheet.Cells[1, 2].Value = "半径";
            sheet.Cells[1, 3].Value = "X坐标";
            sheet.Cells[1, 4].Value = "Y坐标";
            sheet.Cells[1, 5].Value = "Z坐标";
            for (int i = 0; i < datas.Length; i++)
            {
                sheet.Cells[i + 2, 1].Value = i+1;
                sheet.Cells[i + 2, 2].Value = datas[i].R;
                sheet.Cells[i + 2, 3].Value = datas[i].X;
                sheet.Cells[i + 2, 4].Value = datas[i].Y;
                sheet.Cells[i + 2, 5].Value = datas[i].Z;
            }
            book.SaveAs(fileName); //保存工作簿
            excelApp.Quit(); //推出并销毁Excel程序
            excelApp.Dispose();
        }
        /// <summary>
        /// 获取图形对象的数据
        /// </summary>
        /// <param name="db"></param>
        /// <param name="ids"></param>
        /// <returns></returns>
        private CircleData[] GetCircelData(Database db, ObjectId[] ids)
        {
            CircleData[] datas = new CircleData[ids.Length];
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                for (int i = 0; i < ids.Length; i++)
                {
                    Circle c = (Circle)ids[i].GetObject(OpenMode.ForRead);
                    datas[i].X = c.Center.X;
                    datas[i].Y = c.Center.Y;
                    datas[i].Z = c.Center.Z;
                    datas[i].R = c.Radius;
                }
            }
            return datas;
        }
        /// <summary>
        /// 获取文件保存路径和文件名
        /// </summary>
        /// <param name="ed"></param>
        /// <param name="db"></param>
        /// <returns>文件全路径</returns>
        private string OpenSaveDialog(Editor ed,Database db)
        {
            
            string directoryName = Path.GetDirectoryName(db.Filename);
            string fileName = Path.GetFileName(db.Filename);
            fileName = fileName.Substring(0, fileName.IndexOf('.'));
            PromptSaveFileOptions opt = new PromptSaveFileOptions("保存Excel文件");
            opt.DialogCaption = "保存Excel文件";
            opt.Filter = "Excel 97-2003 工作簿(*.xls)|*.xls|Excel 工作簿(*.xlsx)|*.xlsx";
            opt.FilterIndex = 1;
            opt.InitialDirectory = directoryName;
            opt.InitialFileName = fileName;
            PromptFileNameResult fileRes = ed.GetFileNameForSave(opt);
            if (fileRes.Status == PromptStatus.OK)
            {
                fileName = fileRes.StringResult;
            }
            else
            {
                fileName = "";
            }
            return fileName;
        }
        /// <summary>
        /// 获取打开文件的全路径
        /// </summary>
        /// <param name="ed"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        private string OpenFileDialog(Editor ed, Database db)
        {

            string directoryName = Path.GetDirectoryName(db.Filename);
            string fileName = Path.GetFileName(db.Filename);
            fileName = fileName.Substring(0, fileName.IndexOf('.'));
            PromptOpenFileOptions opt = new PromptOpenFileOptions("读取Excel文件");
            opt.DialogCaption = "读取Excel文件";
            opt.Filter = "Excel 工作簿(*.xlsx)|*.xlsx|Excel 97-2003 工作簿(*.xls)|*.xls";
            opt.FilterIndex = 0;
            opt.InitialDirectory = directoryName;
            opt.InitialFileName = fileName;
            PromptFileNameResult fileRes = ed.GetFileNameForOpen(opt);
            if (fileRes.Status == PromptStatus.OK)
            {
                fileName = fileRes.StringResult;
            }
            else
            {
                fileName = "";
            }
            return fileName;
        }
    }
}
